package com.ktdaddy.manager;

import com.ktdaddy.Constants;
import com.ktdaddy.enums.WhaleErrorCode;
import com.ktdaddy.exception.BusinessRuntimeException;
import com.ktdaddy.request.BasePermissionReq;
import com.ktdaddy.request.CreatePermissionReq;
import com.ktdaddy.request.UpdatePermissionReq;
import com.ktdaddy.vo.PermissionMetaVO;
import com.ktdaddy.vo.PermissionNodeVO;
import com.ktdaddy.enums.YesOrNo;
import com.ktdaddy.mapper.KernelRoleRelMapper;
import com.ktdaddy.mapper.PermissionMapper;
import com.ktdaddy.mapper.PermissionMetaMapper;
import com.ktdaddy.mapper.RolePermissionRelMapper;
import com.ktdaddy.pojo.KernelRoleRel;
import com.ktdaddy.pojo.Permission;
import com.ktdaddy.pojo.PermissionMeta;
import com.ktdaddy.pojo.RolePermissionRel;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author kdaddy@163.com
 * @date 2021/7/17 23:06
 */
@Component
public class PermissionManager {

    @Resource
    private PermissionMapper permissionMapper;

    @Resource
    private RolePermissionRelMapper rolePermissionRelMapper;

    @Resource
    private KernelRoleRelMapper kernelRoleRelMapper;

    @Resource
    private PermissionMetaMapper permissionMetaMapper;



    /**
     * 根据角色ID获取权限信息
     * @param roleIds
     * @return
     */
    public List<String> findPermissionByRoleIds(List<Integer> roleIds) {

        Example example = new Example(RolePermissionRel.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andIn("roleId",roleIds);

        List<RolePermissionRel> rolePermissionRelList = rolePermissionRelMapper.selectByExample(example);
        //权限信息去重输出
        List<String> result = rolePermissionRelList.stream().map(RolePermissionRel::getPermissionCode).
                collect(Collectors.toList()).stream().distinct().collect(Collectors.toList());
        return result;
    }

    /**
     * 根据kernelId查询所有根节点
     * @param kernelId
     * @return
     */
    public List<PermissionNodeVO> findRootPermissionByKernelId(Integer kernelId) {
        List<PermissionNodeVO> resultNodes = new ArrayList<>();
        //根据id获取角色
        Example example = new Example(KernelRoleRel.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("kernelId",kernelId);
        List<KernelRoleRel> kernelRoleRelList = kernelRoleRelMapper.selectByExample(example);

        List<Integer>  roleIds = kernelRoleRelList.stream().map(KernelRoleRel::getRoleId).collect(Collectors.toList());
        if(CollectionUtils.isEmpty(roleIds)){
            return resultNodes;
        }

        //根据角色id获取权限
        Example permissionRoleExample = new Example(RolePermissionRel.class);
        Example.Criteria permissionRoleCriteria = permissionRoleExample.createCriteria();
        permissionRoleCriteria.andIn("roleId",roleIds);
        List<RolePermissionRel> rolePermissionRelList = rolePermissionRelMapper.selectByExample(permissionRoleExample);
        List<Integer> permissionIds = rolePermissionRelList.stream().map(RolePermissionRel::getPermissionId).
                collect(Collectors.toList()).stream().distinct().collect(Collectors.toList());

        // 根据ID获取权限
        Example permissionExample = new Example(Permission.class);
        Example.Criteria permissionCriteria = permissionExample.createCriteria();
        permissionCriteria.andIn("id",permissionIds);
        permissionCriteria.andEqualTo("parentId",0);
        permissionCriteria.andEqualTo("status",Constants.STATUS_SUCCESS);
        List<Permission> permissionList = permissionMapper.selectByExample(permissionExample);

        if(CollectionUtils.isEmpty(permissionList)){
            return resultNodes;
        }

        resultNodes = buildResultNodes(permissionList);


        return resultNodes;
    }

    private List<PermissionNodeVO> buildResultNodes(List<Permission> permissionList) {
        List<PermissionNodeVO> permissionNodeBOList = new ArrayList<>();
        for(Permission permission : permissionList){
            PermissionNodeVO permissionNodeBO = new PermissionNodeVO();
            permissionNodeBO.setId(permission.getId());
            permissionNodeBO.setComponent(permission.getComponentUrl());
            permissionNodeBO.setName(permission.getPermissionName());
            permissionNodeBO.setPath(permission.getRoutePath());
            permissionNodeBO.setPermission(permission.getPermissionCode());
            permissionNodeBO.setStatus(permission.getStatus());
            permissionNodeBO.setRedirect(permission.getRedirectPath());
            PermissionMetaVO meta = new PermissionMetaVO();

            PermissionMeta permissionMeta = getByPermissionId(permission.getId());
            if(!Objects.isNull(permissionMeta)){
                meta.setAffix(Constants.DASHBOARD.equals(permission.getPermissionName()));
                meta.setIcon(permissionMeta.getIco());
                meta.setFrameSrc(permissionMeta.getFrameSrc());
                meta.setHideMenu(permissionMeta.getHideMenu().equals(YesOrNo.YES.type));
                meta.setHideChildrenInMenu(permissionMeta.getHideChildrenInMenu().equals(YesOrNo.YES.type));
                meta.setTitle(permissionMeta.getTitle());
                meta.setHideBreadcrumb(permissionMeta.getHideBreadcrumb().equals(YesOrNo.YES.type));
                meta.setShowMenu(permissionMeta.getHideMenu().equals(YesOrNo.NO.type));
                meta.setCurrentActiveMenu(permissionMeta.getCurrentActiveMenu());
                meta.setIgnoreKeepAlive(permissionMeta.getIgnoreKeepAlive().equals(YesOrNo.YES.type));
            }
            permissionNodeBO.setMeta(meta);
            permissionNodeBOList.add(permissionNodeBO);
        }
        return permissionNodeBOList;
    }

    /**
     * 根据权限ID获取元数据
     * @param permissionId
     * @return
     */
    private PermissionMeta getByPermissionId(Integer permissionId){
        Example permissionMetaExample = new Example(PermissionMeta.class);
        Example.Criteria permissionMetaCriteria = permissionMetaExample.createCriteria();
        permissionMetaCriteria.andEqualTo("permissionId",permissionId);
        return permissionMetaMapper.selectOneByExample(permissionMetaExample);
    }

    /**
     * 根据父类节点ID获取子节点信息
     * @param parentId
     * @return
     */
    public List<PermissionNodeVO> findPermissionByParentId(Integer parentId) {
        Example permissionExample = new Example(Permission.class);
        Example.Criteria permissionCriteria = permissionExample.createCriteria();
        permissionCriteria.andEqualTo("parentId",parentId);
        List<Permission> permissionList = permissionMapper.selectByExample(permissionExample);
        return buildResultNodes(permissionList);
    }

    /**
     * 根据名称以及类型查询
     * @param menuName
     * @param type
     * @return
     */
    public Permission findByMenuNameAndType(String menuName, Integer type) {
        Example permissionExample = new Example(Permission.class);
        Example.Criteria permissionCriteria = permissionExample.createCriteria();
        permissionCriteria.andEqualTo("permissionName",menuName);
        permissionCriteria.andEqualTo("permissionType",type);
        return permissionMapper.selectOneByExample(permissionExample);
    }

    @Transactional
    public void savePermission(CreatePermissionReq createPermissionReq) {
        Permission permission = new Permission();

        setCommonField(permission,createPermissionReq);
        Integer result = permissionMapper.insertSelective(permission);
        if(result < 1){
            throw new BusinessRuntimeException(WhaleErrorCode.DB_INSERT_ERROR);
        }
        //往permission_meta中落数据
        PermissionMeta permissionMeta = new PermissionMeta();
        permissionMeta.setPermissionId(permission.getId());
        permissionMeta.setIco(createPermissionReq.getIcon());
        permissionMeta.setIgnoreKeepAlive(createPermissionReq.getKeepalive());
        permissionMeta.setTitle(createPermissionReq.getMenuName());
        permissionMeta.setOrderNo(createPermissionReq.getOrderNo());
        Integer resultMeta = permissionMetaMapper.insertSelective(permissionMeta);
        if(resultMeta < 1){
            throw new BusinessRuntimeException(WhaleErrorCode.DB_INSERT_ERROR);
        }
    }

    /**
     * 获取所有根节点的权限
     * @return
     */
    public List<PermissionNodeVO> findRootPermission() {
        // 根据ID获取权限
        Example permissionExample = new Example(Permission.class);
        Example.Criteria permissionCriteria = permissionExample.createCriteria();
        permissionCriteria.andEqualTo("parentId",0);
        permissionCriteria.andEqualTo("status",Constants.STATUS_SUCCESS);
        List<Permission> permissionList = permissionMapper.selectByExample(permissionExample);
        List<PermissionNodeVO> resultNodes  = buildResultNodes(permissionList);

        return resultNodes;
    }

    /**
     * 根据权限名称查询
     * @param permissionName
     * @return
     */
    public Permission findByPermissionName(String permissionName) {
        Example permissionExample = new Example(Permission.class);
        Example.Criteria permissionCriteria = permissionExample.createCriteria();
        permissionCriteria.andEqualTo("permissionName",permissionName);
        return permissionMapper.selectOneByExample(permissionExample);
    }

    private Permission setCommonField(Permission permission,BasePermissionReq basePermissionReq){
        permission.setPermissionName(basePermissionReq.getMenuName());
        permission.setOrderNo(basePermissionReq.getOrderNo());
        permission.setIco(basePermissionReq.getIcon());
        permission.setRoutePath(basePermissionReq.getRoutePath());
        permission.setPermissionType(basePermissionReq.getType());
        permission.setStatus(basePermissionReq.getStatus());
        permission.setIsExternal(basePermissionReq.getIsExt());
        permission.setIsShow(basePermissionReq.getIsShow());
        permission.setIsCache(basePermissionReq.getKeepalive());
        permission.setPermissionCode(basePermissionReq.getPermission());
        permission.setParentId(basePermissionReq.getParentMenu());
        permission.setComponentUrl(basePermissionReq.getComponent());
        return permission;
    }

    public void updatePermission(UpdatePermissionReq updatePermissionReq) {
        //获取原始权限记录
        Permission permission = permissionMapper.selectByPrimaryKey(updatePermissionReq.getPermissionId());

        setCommonField(permission,updatePermissionReq);
        Integer result = permissionMapper.updateByPrimaryKey(permission);
        if(result < 1){
            throw new BusinessRuntimeException(WhaleErrorCode.DB_UPDATE_ERROR);
        }
        //往permission_meta中落数据
        PermissionMeta permissionMeta = getByPermissionId(updatePermissionReq.getPermissionId());
        permissionMeta.setPermissionId(updatePermissionReq.getPermissionId());
        permissionMeta.setIco(updatePermissionReq.getIcon());
        permissionMeta.setIgnoreKeepAlive(updatePermissionReq.getKeepalive());
        permissionMeta.setTitle(updatePermissionReq.getMenuName());
        permissionMeta.setOrderNo(updatePermissionReq.getOrderNo());
        Integer resultMeta = permissionMetaMapper.updateByPrimaryKey(permissionMeta);
        if(resultMeta < 1){
            throw new BusinessRuntimeException(WhaleErrorCode.DB_INSERT_ERROR);
        }
    }

    @Transactional
    public void deletePermission(Integer permissionId) {
        permissionMapper.deleteByPrimaryKey(permissionId);

        Example permissionMetaExample = new Example(PermissionMeta.class);
        Example.Criteria permissionCriteria = permissionMetaExample.createCriteria();
        permissionCriteria.andEqualTo("permissionId",permissionId);
        Integer result = permissionMetaMapper.deleteByExample(permissionMetaExample);
        if(result < 1){
            throw new BusinessRuntimeException(WhaleErrorCode.DB_DELETE_ERROR);
        }
    }
}
